package com.spsoft.vatoutinv.service.vmshzqrdmanage.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spsoft.core.enums.ResponseEnum;
import com.spsoft.core.exception.BusinessException;
import com.spsoft.core.model.Result;
import com.spsoft.core.model.bo.TokenUser;
import com.spsoft.core.model.leqidmz.param.QueryRedConfirmDetailParam;
import com.spsoft.core.model.leqidmz.response.QueryRedConfirmDetailVO;
import com.spsoft.core.utils.BeanUtils;
import com.spsoft.core.utils.SecurityUtils;
import com.spsoft.core.utils.StringUtil;
import com.spsoft.einvoicetodmz.service.DmzApiClientService;
import com.spsoft.vatoutinv.constants.CommonConstant;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsApprovalHzqrd;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsApprovalHzqrdItem;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsLeqiHzqrd;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsLeqiHzqrdItem;
import com.spsoft.vatoutinv.enums.CommonEnum;
import com.spsoft.vatoutinv.mapper.VmsLeqiHzqrdMapper;
import com.spsoft.vatoutinv.model.dto.vmshzqrdmanage.VmsFsfpxzHzqrdPageDto;
import com.spsoft.vatoutinv.model.vo.vmshzqrdmanage.VmsApprovalHzqrdVo;
import com.spsoft.vatoutinv.model.vo.vmshzqrdmanage.VmsLeqiHzqrdVo;
import com.spsoft.vatoutinv.service.vmsenterpriseinfo.VmsEnterpriseInfoService;
import com.spsoft.vatoutinv.service.vmshzqrdmanage.VmsApprovalHzqrdItemService;
import com.spsoft.vatoutinv.service.vmshzqrdmanage.VmsApprovalHzqrdService;
import com.spsoft.vatoutinv.service.vmshzqrdmanage.VmsLeqiHzqrdItemService;
import com.spsoft.vatoutinv.service.vmshzqrdmanage.VmsLeqiHzqrdService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 红字确认单乐企返回-主表 服务实现类
 * </p>
 *
 * @author chenxudong
 * @since 2024-01-02
 */
@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class VmsLeqiHzqrdServiceImpl extends ServiceImpl<VmsLeqiHzqrdMapper, VmsLeqiHzqrd> implements VmsLeqiHzqrdService {

    public static final String LOG_MSG = "(乐企红字确认单实现层)";

    private final VmsLeqiHzqrdItemService vmsLeqiHzqrdItemService;

    private final VmsApprovalHzqrdService vmsApprovalHzqrdService;

    private final VmsApprovalHzqrdItemService vmsApprovalHzqrdItemService;

    private final VmsEnterpriseInfoService vmsEnterpriseInfoService;

    private final DmzApiClientService dmzApiClientService;

    @Override
    public Result<IPage<VmsLeqiHzqrdVo>> pageHzqrd(VmsFsfpxzHzqrdPageDto pageDto) {
        // 分页查询
        Page<VmsLeqiHzqrd> page = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        LambdaQueryWrapper<VmsLeqiHzqrd> wrapper = new LambdaQueryWrapper<>();

        // 当前登录机构纳税人识别号查询该机构作为“销售方”的红字确认单
        wrapper.eq(VmsLeqiHzqrd::getQydjid, SecurityUtils.getDeptCode());
        wrapper.eq(VmsLeqiHzqrd::getXsfnsrsbh, vmsEnterpriseInfoService.getNsrsbh());
        // 查询本地存储的红字确认单列表信息中已开具红字发票标识为“未开具”
        wrapper.eq(VmsLeqiHzqrd::getYkjhzfpbz, CommonEnum.YKJHZFP_NO.getKey());
        // 查询本地存储的红字确认单列表信息中有效状态为“有效”
        wrapper.eq(VmsLeqiHzqrd::getYxbz, CommonEnum.HZQRD_YXBZ_YES.getKey());
        if (StringUtils.isNotBlank(pageDto.getHzqrxxztdm())) {
            wrapper.eq(VmsLeqiHzqrd::getHzqrxxztdm, pageDto.getHzqrxxztdm());
        } else {
            wrapper.in(VmsLeqiHzqrd::getHzqrxxztdm, CommonEnum.HZQRD_STATUS_01.getKey(), CommonEnum.HZQRD_STATUS_04.getKey());
        }
        wrapper.eq(StringUtil.isNotBlank(pageDto.getChyydm()), VmsLeqiHzqrd::getChyydm, pageDto.getChyydm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getLzfpdm()), VmsLeqiHzqrd::getLzfpdm, pageDto.getLzfpdm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getLzfphm()), VmsLeqiHzqrd::getLzfphm, pageDto.getLzfphm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getHzfpxxqrdbh()), VmsLeqiHzqrd::getHzfpxxqrdbh, pageDto.getHzfpxxqrdbh());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getGmfmc()), VmsLeqiHzqrd::getGmfmc, pageDto.getGmfmc());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getGmfnsrsbh()), VmsLeqiHzqrd::getGmfnsrsbh, pageDto.getGmfnsrsbh());
        if (StringUtil.isNotBlank(pageDto.getLzfpkprqq()) && StringUtil.isNotBlank(pageDto.getLzfpkprqz())) {
            // 蓝字发票开票日期起止
            String lzfpkprqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getLzfpkprqq())), CommonConstant.DATE_FORMAT_14);
            String lzfpkprqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getLzfpkprqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("LZKPRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", lzfpkprqq);
            wrapper.apply("LZKPRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", lzfpkprqz);
        }
        if (StringUtil.isNotBlank(pageDto.getHzqrdsqrqq()) && StringUtil.isNotBlank(pageDto.getHzqrdsqrqz())) {
            // 红字确认单申请日期起止
            String hzqrdsqrqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getHzqrdsqrqq())), CommonConstant.DATE_FORMAT_14);
            String hzqrdsqrqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getHzqrdsqrqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("LRRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdsqrqq);
            wrapper.apply("LRRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdsqrqz);
        }
        if (StringUtil.isNotBlank(pageDto.getHzqrdqrrqq()) && StringUtil.isNotBlank(pageDto.getHzqrdqrrqz())) {
            // 红字确认单确认日期起止
            String hzqrdqrrqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getHzqrdqrrqq())), CommonConstant.DATE_FORMAT_14);
            String hzqrdqrrqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getHzqrdqrrqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("QRRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdqrrqq);
            wrapper.apply("QRRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdqrrqz);
        }
        wrapper.orderByDesc(VmsLeqiHzqrd::getQrrq, VmsLeqiHzqrd::getLrrq, VmsLeqiHzqrd::getId);

        Page<VmsLeqiHzqrd> IPage = this.page(page, wrapper);
        // 将数据库返回数据转换为VO返回前端
        IPage<VmsLeqiHzqrdVo> IPageVo = IPage.convert(item -> {
            VmsLeqiHzqrdVo vo = new VmsLeqiHzqrdVo();
            // 转换数据
            BeanUtils.copyBeanProp(vo, item);
            return vo;
        });

        return Result.OK(IPageVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncSingleLeqiHzqrd(QueryRedConfirmDetailVO hzqrd, TokenUser tokenUser) {
        // 声明乐企红字确认单明细数据，后续使用
        List<QueryRedConfirmDetailVO.Hzqrxxmx> itemList;

        // 1.根据红字确认单编号查询本地乐企数据库是否存在
        LambdaQueryWrapper<VmsLeqiHzqrd> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VmsLeqiHzqrd::getHzfpxxqrdbh, hzqrd.getHzfpxxqrdbh());
        wrapper.eq(VmsLeqiHzqrd::getQydjid, tokenUser.getDeptCode());
        VmsLeqiHzqrd leqiHzqrd = this.getOne(wrapper);
        if (leqiHzqrd == null) {
            // 不存在则新增一条数据
            VmsLeqiHzqrd vmsLeqiHzqrd = new VmsLeqiHzqrd();
            BeanUtils.copyProperties(hzqrd, vmsLeqiHzqrd);
            // 字段名不一样，手动set
            vmsLeqiHzqrd.setLzfppzdm(hzqrd.getLzfppzDm());
            vmsLeqiHzqrd.setLzfptdyslxdm(hzqrd.getLzfpTdyslxDm());
            vmsLeqiHzqrd.setChyydm(hzqrd.getChyyDm());
            vmsLeqiHzqrd.setHzqrxxztdm(hzqrd.getHzqrxxztDm());
            // 红冲税控发票，乐企返回的蓝字发票代码：240421132533，蓝字发票号码：24042113253300444659
            if (StringUtils.isNotBlank(hzqrd.getLzfpdm()) && hzqrd.getLzfphm().length() > 8) {
                vmsLeqiHzqrd.setLzfphm(hzqrd.getLzfphm().replace(hzqrd.getLzfpdm(), ""));
            }
            // 红字确认单来源、创建人、更新人等
            String hzqrdSource = judgeHzqrdSource(vmsLeqiHzqrd, vmsEnterpriseInfoService.getNsrsbh(tokenUser.getDeptCode()));
            vmsLeqiHzqrd.setHzqrdly(hzqrdSource);
            vmsLeqiHzqrd.setQydjid(tokenUser.getDeptCode());
            vmsLeqiHzqrd.setCreatTime(new Date());
            vmsLeqiHzqrd.setCreatBy(tokenUser.getUserCode());
            vmsLeqiHzqrd.setUpdateTime(new Date());
            vmsLeqiHzqrd.setUpdateBy(tokenUser.getUserCode());
            this.save(vmsLeqiHzqrd);

            // 入参如果有明细信息，不用调乐企接口
            if (CollectionUtil.isNotEmpty(hzqrd.getHzqrxxmxList())) {
                itemList = hzqrd.getHzqrxxmxList();
            } else {
                // 调用乐企接口查询数电红字确认单明细信息
                QueryRedConfirmDetailParam itemParam = new QueryRedConfirmDetailParam();
                itemParam.setXsfnsrsbh(vmsLeqiHzqrd.getXsfnsrsbh());
                itemParam.setUuid(vmsLeqiHzqrd.getUuid());
                itemParam.setCreateUser(tokenUser.getUserCode());
                itemParam.setDeptCode(tokenUser.getDeptCode());
                Result<QueryRedConfirmDetailVO> itemResult = dmzApiClientService.queryRedConfirmDetail(itemParam, null);
                if (ResponseEnum.SUCCESS.getCode().equals(itemResult.getCode())) {
                    log.info("{}调用DMZ查询数电红字确认单明细成功", LOG_MSG);
                    itemList = itemResult.getData().getHzqrxxmxList();
                } else {
                    log.error("{}调用DMZ查询数电红字确认单明细失败，原因：{}", LOG_MSG, itemResult.getMessage());
                    throw new BusinessException(itemResult.getCode(), itemResult.getMessage());
                }
            }
            // 插入红字确认单明细信息
            if (CollectionUtil.isNotEmpty(itemList)) {
                List<VmsLeqiHzqrdItem> vmsLeqiHzqrdItemList = BeanUtils.copyListProperties(itemList, VmsLeqiHzqrdItem::new, (s, t) -> {
                    t.setHzqrdId(vmsLeqiHzqrd.getId());
                    t.setHzfpxxqrdbh(vmsLeqiHzqrd.getHzfpxxqrdbh());
                });
                // 根据明细序号升序排序入库
                vmsLeqiHzqrdItemList = vmsLeqiHzqrdItemList.stream().sorted(Comparator.comparing(VmsLeqiHzqrdItem::getXh)).collect(Collectors.toList());
                vmsLeqiHzqrdItemService.saveBatch(vmsLeqiHzqrdItemList);
            }
        } else {
            // 存在则更新数据，全部字段都以乐企返回为准
            BeanUtils.copyProperties(hzqrd, leqiHzqrd);
            // 字段名不一样，手动set
            leqiHzqrd.setLzfppzdm(hzqrd.getLzfppzDm());
            leqiHzqrd.setLzfptdyslxdm(hzqrd.getLzfpTdyslxDm());
            leqiHzqrd.setChyydm(hzqrd.getChyyDm());
            leqiHzqrd.setHzqrxxztdm(hzqrd.getHzqrxxztDm());
            // 红冲税控发票，乐企返回的蓝字发票代码：240421132533，蓝字发票号码：24042113253300444659
            if (StringUtils.isNotBlank(hzqrd.getLzfpdm()) && hzqrd.getLzfphm().length() > 8) {
                leqiHzqrd.setLzfphm(hzqrd.getLzfphm().replace(hzqrd.getLzfpdm(), ""));
            }
            // 红字确认单来源、更新人等
            String hzqrdSource = judgeHzqrdSource(leqiHzqrd, vmsEnterpriseInfoService.getNsrsbh(tokenUser.getDeptCode()));
            leqiHzqrd.setHzqrdly(hzqrdSource);
            leqiHzqrd.setQydjid(tokenUser.getDeptCode());
            leqiHzqrd.setUpdateTime(new Date());
            leqiHzqrd.setUpdateBy(tokenUser.getUserCode());
            this.updateById(leqiHzqrd);

            // 入参如果有明细信息，不用调用乐企接口
            if (CollectionUtil.isNotEmpty(hzqrd.getHzqrxxmxList())) {
                itemList = hzqrd.getHzqrxxmxList();
            } else {
                QueryRedConfirmDetailParam itemParam = new QueryRedConfirmDetailParam();
                itemParam.setXsfnsrsbh(leqiHzqrd.getXsfnsrsbh());
                itemParam.setUuid(leqiHzqrd.getUuid());
                itemParam.setCreateUser(tokenUser.getUserCode());
                itemParam.setDeptCode(tokenUser.getDeptCode());
                Result<QueryRedConfirmDetailVO> itemResult = dmzApiClientService.queryRedConfirmDetail(itemParam, null);
                if (ResponseEnum.SUCCESS.getCode().equals(itemResult.getCode())) {
                    log.info("{}调用DMZ查询数电红字确认单明细成功", LOG_MSG);
                    itemList = itemResult.getData().getHzqrxxmxList();
                } else {
                    log.error("{}调用DMZ查询数电红字确认单明细失败，原因：{}", LOG_MSG, itemResult.getMessage());
                    throw new BusinessException(itemResult.getCode(), itemResult.getMessage());
                }
            }
            // 更新红字确认单明细信息
            if (CollectionUtil.isNotEmpty(itemList)) {
                // 明细信息先删除在新增
                LambdaQueryWrapper<VmsLeqiHzqrdItem> removeWrapper = new LambdaQueryWrapper<>();
                removeWrapper.eq(VmsLeqiHzqrdItem::getHzqrdId, leqiHzqrd.getId());
                vmsLeqiHzqrdItemService.remove(removeWrapper);
                // 数据转换
                List<VmsLeqiHzqrdItem> vmsLeqiHzqrdItemList = BeanUtils.copyListProperties(itemList, VmsLeqiHzqrdItem::new, (s, t) -> {
                    t.setHzqrdId(leqiHzqrd.getId());
                    t.setHzfpxxqrdbh(leqiHzqrd.getHzfpxxqrdbh());
                });
                // 根据明细序号升序排序入库
                vmsLeqiHzqrdItemList = vmsLeqiHzqrdItemList.stream().sorted(Comparator.comparing(VmsLeqiHzqrdItem::getXh)).collect(Collectors.toList());
                vmsLeqiHzqrdItemService.saveBatch(vmsLeqiHzqrdItemList);
            }
        }

        // 2.根据红字确认单编号查询红字确认单流程数据库是否存在
        LambdaQueryWrapper<VmsApprovalHzqrd> query = new LambdaQueryWrapper<>();
        query.eq(VmsApprovalHzqrd::getHzfpxxqrdbh, hzqrd.getHzfpxxqrdbh());
        query.eq(VmsApprovalHzqrd::getQydjid, tokenUser.getDeptCode());
        VmsApprovalHzqrd approvalHzqrd = vmsApprovalHzqrdService.getOne(query);
        if (approvalHzqrd != null) {
            // 存在则更新数据
            BeanUtils.copyProperties(hzqrd, approvalHzqrd);
            // 字段名不一样，手动set
            approvalHzqrd.setLzfppzdm(hzqrd.getLzfppzDm());
            approvalHzqrd.setLzfptdyslxdm(hzqrd.getLzfpTdyslxDm());
            approvalHzqrd.setChyydm(hzqrd.getChyyDm());
            approvalHzqrd.setHzqrxxztdm(hzqrd.getHzqrxxztDm());
            // 红冲税控发票，乐企返回的蓝字发票代码：240421132533，蓝字发票号码：24042113253300444659
            if (StringUtils.isNotBlank(hzqrd.getLzfpdm()) && hzqrd.getLzfphm().length() > 8) {
                approvalHzqrd.setLzfphm(hzqrd.getLzfphm().replace(hzqrd.getLzfpdm(), ""));
            }
            // 交易机构、更新人等
            approvalHzqrd.setQydjid(tokenUser.getDeptCode());
            approvalHzqrd.setUpdateTime(new Date());
            approvalHzqrd.setUpdateBy(tokenUser.getUserCode());
            vmsApprovalHzqrdService.updateById(approvalHzqrd);

            // 乐企数电红字确认单明细信息
            if (CollectionUtil.isNotEmpty(itemList)) {
                // 明细信息先删除在新增
                LambdaQueryWrapper<VmsApprovalHzqrdItem> removeWrapper = new LambdaQueryWrapper<>();
                removeWrapper.eq(VmsApprovalHzqrdItem::getHzqrdId, approvalHzqrd.getId());
                vmsApprovalHzqrdItemService.remove(removeWrapper);
                // 数据转换
                List<VmsApprovalHzqrdItem> approvalHzqrdItemList = BeanUtils.copyListProperties(itemList, VmsApprovalHzqrdItem::new, (s, t) -> {
                    t.setHzqrdId(approvalHzqrd.getId());
                    t.setHzfpxxqrdbh(approvalHzqrd.getHzfpxxqrdbh());
                });
                // 根据明细序号升序排序入库
                approvalHzqrdItemList = approvalHzqrdItemList.stream().sorted(Comparator.comparing(VmsApprovalHzqrdItem::getXh)).collect(Collectors.toList());
                vmsApprovalHzqrdItemService.saveBatch(approvalHzqrdItemList);
            }
        }
    }

    /**
     * 判断红字确认单来源
     *
     * @param hzqrd  红字确认单信息
     * @param nsrsbh 登录机构税号
     * @return 0：我发出的红字确认单 1：我收到的红字确认单
     */
    private String judgeHzqrdSource(VmsLeqiHzqrd hzqrd, String nsrsbh) {
        if (StringUtils.isBlank(nsrsbh)) {
            throw new BusinessException(ResponseEnum.ENTERPRISEINFO_ERROR);
        }
        if (CommonEnum.LRFSF_GMF.getKey().equals(hzqrd.getLrfsf())) {
            return nsrsbh.equals(hzqrd.getGmfnsrsbh()) ? CommonEnum.HZQRD_SOURCE_0.getKey() : CommonEnum.HZQRD_SOURCE_1.getKey();
        } else {
            return nsrsbh.equals(hzqrd.getXsfnsrsbh()) ? CommonEnum.HZQRD_SOURCE_0.getKey() : CommonEnum.HZQRD_SOURCE_1.getKey();
        }
    }
}
